package org.mech.sefer.client.ui.spring.task;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.mech.sefer.shared.common.CollectionUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * <p>
 * The ReflectionTaskCreator is bean that creates task for each method in
 * class/interface and register the task into task registry.
 * </p>
 * <p>
 * Date: 25.4.2012 8:49:03
 * </p>
 * 
 * @author martin.krajc
 */
@SuppressWarnings("rawtypes")
public class ReflectionTaskCreator implements ApplicationContextAware {

	private ApplicationContext context;
	private List<Class> interfacesToParse;
	
	@Resource(name="taskRegistry")
	private TaskRegistry registry;

	@PostConstruct
	public void create() {
		if(CollectionUtils.isNotEmpty(interfacesToParse)){
			
			for(Class<?> iClass: interfacesToParse){
				if(!iClass.isInterface()){
					throw new IllegalArgumentException("Class '"+iClass+"' is not interface");
				}
				
				Map<String, ?> beans = context.getBeansOfType(iClass);
				
				if(CollectionUtils.isEmpty(beans)){
					throw new IllegalArgumentException("No instance of type of interface '"+iClass+"' found in context");
				}
				
				Object bean = beans.values().iterator().next();
				
				Method[] methods= iClass.getMethods();
				
				for(Method method : methods){
					ReflectionTask task = new ReflectionTask();
					task.setMethod(method);
					task.setBean(bean);
					
					registry.registerTask(registry.createKey(method.getName(), iClass), task);
				}
			}
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext context)
			throws BeansException {
		this.context = context;
	}

	public List<Class> getInterfacesToParse() {
		return interfacesToParse;
	}

	public void setInterfacesToParse(List<Class> interfacesToParse) {
		this.interfacesToParse = interfacesToParse;
	}

}
